home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Snippets / MultiWin TE⁄Undo⁄S_H 1.0.1 / MultiWin TE⁄Undo⁄S_H.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-16  |  28.9 KB  |  1,277 lines  |  [TEXT/KAHL]

  1. /*
  2.     MultiWin TE/Undo/S_H Demo 1.0.1
  3.     By Eric Long.
  4.     
  5.     Original Show_Help code by James Walker.  This version modified by Eric Long.
  6.     
  7.     Changes in 1.0.1: Corrected assignment of var windowID in HandleKeyDown
  8.                       routine; made it a long.
  9.     
  10.     This project was compiled with THINK C v.7.x without Universal Headers.
  11.     I could not get the code to compile under Universal Headers.
  12.     I received an error saying "ScrapInfo" was undefined.  ???
  13.     
  14.     If Mac file names were longer, this project would be titled:
  15.     
  16.         Multiple (Dialog)Window TextEdit and Edit Menu Handling w/ Undo,
  17.             plus a modified modeless version of Show_Help (original code
  18.                 by James Walker) Demo.
  19.                 
  20.     I shortened up the title the best I could. (-:
  21.         
  22.     This project was launched to teach myself a number of things.  I hadn't
  23.     handled multiple windows with TE items before, nor had I ever supported the
  24.     Edit menu myself, and I needed to develop code to handle Undo.  I also wanted
  25.     to make James Walker's Show_Help code work as a modeless dialog. This
  26.     archive is distributed with his permission.
  27.     
  28.     I wasn't able to locate code examples of handling Undo. I'm sure it
  29.     will help to have this available for others to peek at.  I also know
  30.     from my experience that a lot of code examples that are available are
  31.     difficult for those learning to assimilate.  I haven't yet learned all
  32.     those fancy compiler techniques with the #pragmas and whatnot, I am
  33.     still following the formatting I learned when I first read Dave Mark's
  34.     "Mac Programming Primer Vol.1", I don't know the benefits of assigning
  35.     vars to registers, nor do I write inline assembler as yet.  Those things
  36.     considered, I figure my code is very easy for learners to follow!  No
  37.     doubt all of us learners that stick with it will someday be writing code
  38.     that takes advantage of all those tricks, but until then, here's some code
  39.     you can read and understand!
  40.     
  41.     James Walker's Show_Help code is fairly complex.  It's helped me learn a
  42.     great deal.  It's also taken me awhile to understand it.  I think if anyone
  43.     wants to dig into TE, he provides a lot to chew on...  _and_ if I keep
  44.     reading DEVELOP, I may even figure it all out someday!  I tried to keep
  45.     the routines for the modeless Show_Help all together in the same source file.
  46.     I created some similiar routines in this source file (FlashButton).  I know
  47.     it is redundant, but I thought it would make it easy to seperate the two, if
  48.     you want to weed one out from the other.
  49.     
  50.     Show_Help is in the public domain.  This code is entered as well.  Use it,
  51.     or any part of it, as you like; free and clear.  It will require some minor
  52.     changes to be 6 compatible.  You'll need to add code to position your windows
  53.     and you might need to check for WaitNextEvent trap.  I'm not sure if that is
  54.     available in 6.  SystemTask() will help you in conjunction with GetNextEvent
  55.     in that case.  I don't think there's much else that would conflict with 6.
  56.     
  57.     Best Regards.  Eric
  58. */
  59.  
  60. /*     konstants     */
  61.  
  62. #define     kBaseResID                128
  63. #define     kSleep                    20L
  64. #define     k255Characters            255
  65. #define     kMaxTextPosition        32767
  66. #define     kGenericDlgStorage        (sizeof(DialogRecord))
  67.  
  68. #define        RETURN_CHAR        0x0D
  69. #define        TILDE_CHAR        0x7E
  70. #define        ENTER_CHAR        0x03
  71. #define        ESCAPE_CHAR        0x1B
  72. #define         OPTION_KEY        0x3A
  73.  
  74. #define         sEmptyString    "\p"
  75.  
  76. #define         kDefaultButton    1
  77. #define         kCancelButton    2
  78. #define         kOnlyButton        3
  79.  
  80. #define     kAboutAlertID            500
  81. #define     rErrorAlertID            501
  82. #define     rShowHelpDlg            128
  83.  
  84.     // Items for both generic dialogs
  85. #define         iDefaultOutline        2
  86. #define         iEditText            5
  87.  
  88. #define     rGenericDlg1            129
  89. #define         iRadioYes            6
  90. #define         iRadioNo            7
  91. #define         iCheckBox            9
  92.  
  93. #define     rGenericDlg2            130
  94. #define         iRadioFirstDay        6
  95. #define         iFirstCheckBox        14
  96.  
  97.  
  98. /* Window Stuff */
  99. #define    kMoveToFront        (WindowPtr)-1L
  100. #define       kMax_WindowsOpen    10
  101.  
  102. /* Menus */
  103. #define        mApple            kBaseResID+1
  104. #define             iAbout        1
  105. #define        mFile            kBaseResID+2
  106. #define             iOpenGenDlg1    1
  107. #define             iOpenGenDlg2    2                
  108. #define             iClose        4
  109. #define             iHelp        6
  110. #define             iQuit        8
  111. #define         mEdit            kBaseResID
  112. #define             iUndo        1
  113. #define             iCut        3
  114. #define             iCopy        4
  115. #define             iPaste        5
  116. #define             iClear        6
  117. #define             iSelectAll    8
  118.  
  119.  
  120. /* Help screen Info */
  121. #define        kHelp_info_id        kBaseResID
  122.  
  123. /* Error Strings */
  124. #define         rErrStringsID        128
  125. #define             eCantOpenNewWindow    1
  126. #define             eNotEnoughMem        2
  127. #define             eDialogNotFound        3
  128.  
  129.  
  130. typedef struct{
  131. Str255        undoString;
  132. short        undoItem;
  133. short        undoSelStart;
  134. short        undoSelEnd;
  135. } My_UndoRec;
  136.  
  137.  
  138. /************************* Globals ******************************/
  139.  
  140. Boolean            gDone, gCanUndo = false;
  141. short            gWindowsOpen = 0;    // Total #windows presently open
  142. TEHandle        gCur_DlgText;    // Currently active TE item
  143. My_UndoRec        gUndo_Info;
  144.  
  145.  
  146. /************************ Prototypes **********************************/
  147.  
  148. void            main( void );
  149. void            ToolBoxInit ( void );
  150. void            MenuBarInit( void );
  151. void            ScrapInit( void );
  152. void            EventLoop ( void );
  153. void            DoEvent( EventRecord *eventPtr );                            
  154. void            DoUpdate( WindowPtr window );
  155. void            HandleNull( EventRecord *event );
  156. void            HandleActivate( EventRecord *eventPtr );
  157. void            HandleOSEvent( EventRecord *eventPtr );
  158. void            HandleKeyDown(EventRecord *eventPtr);
  159. void            HandleMouseDown (EventRecord *eventPtr );
  160. void            HandleMenuChoice( EventRecord *event );
  161. void            HandleAppleChoice( short item );
  162. void            HandleFileChoice( short item );
  163. void            HandleEditChoice( EventRecord *event, short item );
  164. pascal void        buttonProc( DialogPtr theDialog, short item );
  165. void            Init_GenericDlg1( void );
  166. void            Init_GenericDlg2( void );
  167. void            Handle_GenericDialog( EventRecord *event, long whichDlg );
  168. void            ProcessEvt_GenericDlg1( DialogPtr dialog, short iHit );
  169. void            ProcessEvt_GenericDlg2( DialogPtr dialog, short iHit );
  170. void            Close_GenericDialog(DialogPtr dialog);
  171. void            Adjust_Generic_EditMenu( DialogPtr dialog );
  172. void            Do_Undo( DialogPtr dialog );
  173. My_UndoRec        Get_UndoInfo(DialogPeek dialog);
  174. void            Maintain_EditMenu( DialogPtr dialog, My_UndoRec *preEditState );
  175. void            AdjustMenu( short menuID, short item, Boolean switchOn );
  176. Boolean            Keydown_Button( EventRecord *event, short item_number,
  177.                              short buttonKind);
  178. void            FlashButton( short item_number );
  179. void            Close_AllDialogs( void );    // Option-click in goAway, or Quit
  180. short            isPressed(unsigned short k );
  181. Boolean            Can_OpenMoreWindows( void );
  182. void            DoError( short err, Boolean fatal );
  183.  
  184. /* Prototypes: For Modeless Show_Help */
  185. void             Init_Show_help( short help_info_id );
  186. void            Handle_ShowHelp( EventRecord *event, DialogPtr dialog );
  187. void            Close_ShowHelp(DialogPtr dptr);
  188. void            Do_ShowHelp_Copy( DialogPtr showHelpDlg );
  189.  
  190.  
  191.  
  192. /******************** main ***********************************/
  193.  
  194. void        main ( void )
  195. {
  196.         ToolBoxInit ();
  197.         MaxApplZone();
  198.         MenuBarInit();
  199.         ScrapInit();
  200.             
  201.         FlushEvents( everyEvent, 0 );        
  202.         EventLoop();
  203.         LoadScrap();    // Make sure scrap is in memory, not left out on a disk 
  204. }
  205.         
  206.  
  207. /************************* ToolBoxInit ******************************/
  208.  
  209. void        ToolBoxInit ( void )
  210. {
  211.     InitGraf ( &thePort );
  212.     InitFonts ();
  213.     InitWindows ();
  214.     InitMenus ();
  215.     TEInit ();
  216.     InitDialogs ( nil );
  217.     InitCursor ();
  218. }
  219.  
  220.  
  221. /*********************** MenuBarInit ***************************/
  222.  
  223. void    MenuBarInit( void )
  224. {
  225.     Handle            menuBar;
  226.     MenuHandle        menu;
  227.     Str255            directionStr;
  228.     
  229.     menuBar = GetNewMBar( kBaseResID );
  230.     SetMenuBar( menuBar );
  231.     
  232.     menu = GetMHandle( mApple );
  233.     AddResMenu( menu, 'DRVR' );
  234.     
  235.     DrawMenuBar();
  236. }
  237.  
  238.  
  239. /************************** ScrapInit *******************************/ 
  240.  
  241. void    ScrapInit( void )
  242. {
  243.     if (ScrapInfo.scrapState < 0)
  244.         ZeroScrap();
  245.     else
  246.         TEFromScrap();    // Copy Desk Scrap into TE Scrap
  247.     
  248.     gUndo_Info.undoString[0] = 0;
  249. }
  250.  
  251.  
  252. /************************ EventLoop ************************/
  253.  
  254. void    EventLoop ( void )
  255. {
  256.     EventRecord        event;
  257.     WindowPtr        dialog;
  258.     
  259.     gDone = false;
  260.  
  261.     while ( !gDone )
  262.     {
  263.         if ( WaitNextEvent( everyEvent, &event, kSleep, nil) )
  264.                 DoEvent ( &event );
  265.         else
  266.             HandleNull( &event );
  267.     }
  268. }
  269.  
  270.  
  271. /************************** DoEvent ***********************/
  272.  
  273. void    DoEvent( EventRecord *eventPtr )
  274. {        
  275.     WindowPtr    theWindow;
  276.     
  277.     switch ( eventPtr->what )
  278.     {
  279.         case activateEvt:
  280.             HandleActivate(eventPtr);
  281.             break;
  282.         case keyDown:
  283.         case autoKey:
  284.             HandleKeyDown(eventPtr);
  285.             break;
  286.         case mouseDown:
  287.             HandleMouseDown( eventPtr );
  288.             break;
  289.         case updateEvt:
  290.             DoUpdate((WindowPtr)eventPtr->message);
  291.             break;
  292.         case osEvt:
  293.             HandleOSEvent( eventPtr );
  294.             break;
  295.     }             
  296. }
  297.  
  298.  
  299. /********************* DoUpdate ******************************/
  300.  
  301. void        DoUpdate( WindowPtr    window )
  302. {
  303.     GrafPtr    savePort;
  304.         
  305.     GetPort(&savePort);
  306.     SetPort(window);
  307.     
  308.     BeginUpdate( window );
  309.     
  310.     if (((WindowPeek)(window))->windowKind == dialogKind)
  311.         UpdtDialog((DialogPtr)window, window->visRgn);
  312.         
  313.     EndUpdate( window );
  314.     
  315.     SetPort(savePort);
  316. }
  317.  
  318.  
  319. /******************* HandleNull **************************/
  320.  
  321. void    HandleNull( EventRecord *eventPtr )
  322. {
  323.     GrafPtr    thePort;
  324.     long    windowID;
  325.     
  326.     GetPort(&thePort);
  327.     
  328.     windowID = GetWRefCon(thePort);
  329.     switch (windowID)
  330.     {
  331.         case rShowHelpDlg:
  332.             Handle_ShowHelp( eventPtr, (DialogPtr)thePort );    // TEIdle
  333.             break;
  334.         case rGenericDlg1:
  335.         case rGenericDlg2:
  336.             Handle_GenericDialog(eventPtr, windowID );
  337.             break;
  338.     }
  339. }        
  340.  
  341.  
  342. /************************ HandleActivate *******************************/ 
  343.  
  344. void    HandleActivate( EventRecord *eventPtr )
  345. {
  346.     WindowPtr    theWindow;
  347.     DialogPeek    dlgPeek;
  348.     short        iType;
  349.     Rect        iRect;
  350.     
  351.     theWindow = (WindowPtr)(eventPtr->message);
  352.     
  353.     
  354.     if (IsDialogEvent(eventPtr))
  355.     {
  356.         switch (GetWRefCon(theWindow))
  357.         {
  358.             case rShowHelpDlg:
  359.                 Handle_ShowHelp(eventPtr, (DialogPtr)theWindow);
  360.                 break;
  361.             case rGenericDlg1:
  362.             case rGenericDlg2:
  363.                 dlgPeek = (DialogPeek)theWindow;
  364.                 if (eventPtr->modifiers & activeFlag)
  365.                 {
  366.                     SetPort(theWindow);
  367.                     gCur_DlgText = (dlgPeek->textH);
  368.                     TEActivate(gCur_DlgText);
  369.                     Adjust_Generic_EditMenu((DialogPtr)theWindow );
  370.                 }
  371.                 else
  372.                 {
  373.                     TEDeactivate((dlgPeek->textH));
  374.                         // Maintain Undo
  375.                     gCanUndo = false;
  376.                 }
  377.                 break;
  378.         }
  379.     }
  380. }
  381.  
  382.  
  383. /************************ HandleOSEvent *******************************/ 
  384.  
  385. void    HandleOSEvent( EventRecord *eventPtr )
  386. {
  387.     WindowPtr    theWindow;
  388.     DialogPeek    dlgPeek;
  389.     short        iType;
  390.     Rect        iRect;
  391.     
  392.     theWindow = FrontWindow();    
  393.     switch (GetWRefCon(theWindow))
  394.     {
  395.         case rShowHelpDlg:
  396.             Handle_ShowHelp(eventPtr, (DialogPtr)theWindow);
  397.             break;
  398.         case rGenericDlg1:
  399.         case rGenericDlg2:
  400.             dlgPeek = (DialogPeek)theWindow;
  401.             if (eventPtr->message & resumeFlag)
  402.             {
  403.                 gCur_DlgText = (dlgPeek->textH);
  404.                 TEActivate(gCur_DlgText);                
  405.                 Adjust_Generic_EditMenu((DialogPtr)theWindow );
  406.             }
  407.             else
  408.             {
  409.                 TEDeactivate((dlgPeek->textH));
  410.                     // Maintain Undo
  411.                 gCanUndo = false;
  412.             }
  413.             break;
  414.     }
  415.         // Update desk scrap or receive update from desk scrap
  416.     if (eventPtr->message & resumeFlag)
  417.         TEFromScrap();
  418.     else
  419.     {
  420.         ZeroScrap();
  421.         TEToScrap();
  422.     }
  423. }
  424.  
  425.  
  426. /******************** HandleKeyDown ****************************/
  427.  
  428. void    HandleKeyDown(EventRecord *eventPtr)
  429. {
  430.     WindowPtr    window;
  431.     long        windowID;
  432.         
  433.     if ((eventPtr->modifiers & cmdKey) != 0)
  434.         HandleMenuChoice( eventPtr );
  435.     else
  436.     {
  437.         window = FrontWindow();
  438.         windowID = GetWRefCon(window);
  439.         switch (windowID)
  440.         {
  441.             case rShowHelpDlg:
  442.                 Handle_ShowHelp( eventPtr, window);
  443.                 break;
  444.             case rGenericDlg1:
  445.             case rGenericDlg2:
  446.                 Handle_GenericDialog( eventPtr, windowID);
  447.                 break;
  448.         }
  449.     }
  450. }
  451.  
  452.  
  453. /******************* HandleMouseDown **************************/
  454.  
  455. void    HandleMouseDown ( EventRecord *eventPtr )
  456. {
  457.     WindowPtr        window;
  458.     short            thePart;
  459.     long            windowID;
  460.     long            the_text;
  461.     DialogPeek        theDialogPtr;
  462.     
  463.     thePart = FindWindow ( eventPtr->where, &window );        
  464.     windowID = GetWRefCon(window);
  465.     if ((thePart >= inContent) && (window != (WindowPtr)thePort))
  466.         SelectWindow(window);
  467.     else
  468.     {
  469.         switch ( thePart )
  470.         {
  471.             case inMenuBar:
  472.                 HandleMenuChoice( eventPtr );
  473.                 break;
  474.             case inSysWindow :
  475.                 SystemClick ( eventPtr, window );
  476.                 break;
  477.             case inDrag :
  478.                 DragWindow ( window, eventPtr->where,
  479.                             &screenBits.bounds );
  480.                 break;
  481.             case inGoAway:
  482.                 if (TrackGoAway(window, eventPtr->where))
  483.                 {
  484.                     if (isPressed(OPTION_KEY))    // Option-click in goAway, close everything
  485.                         Close_AllDialogs();
  486.                     else
  487.                     {
  488.                         switch(windowID)
  489.                         {
  490.                             case rShowHelpDlg:
  491.                                 Close_ShowHelp((DialogPtr)window);
  492.                                 break;
  493.                             case rGenericDlg1:
  494.                             case rGenericDlg2:
  495.                                 Close_GenericDialog((DialogPtr)window);
  496.                                 break;
  497.                         }
  498.                     }
  499.                 }
  500.  
  501.                 if (!gWindowsOpen)
  502.                     AdjustMenu(mFile, iClose, false);
  503.                 break;
  504.             case inContent:
  505.                 switch (windowID)
  506.                 {
  507.                     case rShowHelpDlg:
  508.                         Handle_ShowHelp(eventPtr, (DialogPtr)window );
  509.                         break;
  510.                     case rGenericDlg1:
  511.                     case rGenericDlg2:
  512.                         Handle_GenericDialog(eventPtr, windowID);
  513.                         break;
  514.                 }
  515.                 break;
  516.         }
  517.     }
  518. }
  519.  
  520.  
  521. /********************** HandleMenuChoice **************************/
  522.  
  523. void    HandleMenuChoice( EventRecord *event )
  524. {
  525.     long        menuChoice;
  526.     short        menu;
  527.     short        item;
  528.     char        theChar;
  529.     
  530.     if ((event->what == keyDown) || (event->what == autoKey))
  531.     {
  532.         theChar = event->message & charCodeMask;
  533.         menuChoice = (MenuKey(theChar));
  534.     }
  535.     else
  536.         menuChoice = MenuSelect( event->where );
  537.         
  538.     if ( menuChoice != 0 )
  539.     {
  540.         menu = HiWord( menuChoice );
  541.         item = LoWord( menuChoice );
  542.         
  543.         switch( menu )
  544.         {
  545.             case mApple:
  546.                 HandleAppleChoice( item );
  547.                 break;
  548.             case mFile:
  549.                 HandleFileChoice( item );
  550.                 break;
  551.             case mEdit:
  552.                 HandleEditChoice( event, item );
  553.                 break;
  554.         }
  555.         HiliteMenu( 0 );
  556.     }
  557. }
  558.  
  559.  
  560. /********************* HandleAppleChoice ***************************/
  561.  
  562. void    HandleAppleChoice( short item )
  563. {
  564.     MenuHandle    appleMenu;
  565.     Str255        accName;
  566.     short        accNumber;
  567.     
  568.     switch ( item )
  569.     {
  570.         case iAbout:
  571.             Alert(kAboutAlertID, nil);
  572.             break;
  573.         default:
  574.             appleMenu = GetMHandle( mApple );
  575.             GetItem( appleMenu, item, accName );
  576.             accNumber = OpenDeskAcc( accName );
  577.             break;
  578.     }
  579. }
  580.  
  581.  
  582. /********************* HandleFileChoice ****************************/
  583.  
  584. void    HandleFileChoice( short item )
  585. {            
  586.     long        the_text, windowID;
  587.     DialogPeek    theDialogPtr;
  588.  
  589.     switch(item)
  590.     {
  591.         case iOpenGenDlg1:
  592.             if (Can_OpenMoreWindows())
  593.                 Init_GenericDlg1();
  594.             break;
  595.         case iOpenGenDlg2:
  596.             if (Can_OpenMoreWindows())
  597.                 Init_GenericDlg2();
  598.             break;
  599.         case iClose:
  600.             windowID = GetWRefCon(thePort);
  601.             switch(windowID)
  602.             {
  603.                 case rShowHelpDlg:
  604.                     Close_ShowHelp((DialogPtr)thePort);
  605.                     break;
  606.                 case rGenericDlg1:
  607.                 case rGenericDlg2:
  608.                     Close_GenericDialog((DialogPtr)thePort);
  609.                     break;
  610.             }
  611.             break;
  612.         case iHelp:
  613.             if (Can_OpenMoreWindows())
  614.                 Init_Show_help( kHelp_info_id );
  615.             break;
  616.         case iQuit:
  617.             if (gWindowsOpen)
  618.                 Close_AllDialogs();
  619.             gDone = true;
  620.             break;
  621.     }
  622. }
  623.  
  624.  
  625. /********************* HandleEditChoice ******************************/
  626.  
  627. void        HandleEditChoice( EventRecord *event, short item )
  628. {
  629.     DialogPtr    activeWindow;
  630.     long        windowID;
  631.     
  632.     activeWindow = FrontWindow();
  633.     
  634.     if (activeWindow)
  635.     {
  636.         windowID = GetWRefCon(activeWindow);
  637.         switch (item)
  638.         {
  639.             case iUndo:
  640.                 if (gCanUndo)
  641.                     Do_Undo(activeWindow);
  642.                 break;
  643.             case iCut:
  644.                 gUndo_Info = Get_UndoInfo(activeWindow);
  645.                 gCanUndo = true;
  646.                 DlgCut(activeWindow);
  647.                 Adjust_Generic_EditMenu(activeWindow);
  648.                 break;
  649.             case iCopy:
  650.                 switch (windowID)
  651.                 {
  652.                     case rShowHelpDlg:
  653.                         Do_ShowHelp_Copy(activeWindow);
  654.                         break;
  655.                     case rGenericDlg1:
  656.                     case rGenericDlg2:
  657.                         DlgCopy(activeWindow);
  658.                         Adjust_Generic_EditMenu(activeWindow);
  659.                         break;
  660.                 }
  661.                 break;
  662.             case iPaste:
  663.                 gUndo_Info = Get_UndoInfo(activeWindow);
  664.                 gCanUndo = true;
  665.                 DlgPaste(activeWindow);
  666.                 Adjust_Generic_EditMenu(activeWindow);
  667.                 break;
  668.             case iClear:
  669.                 gUndo_Info = Get_UndoInfo(activeWindow);
  670.                 gCanUndo = true;
  671.                 DlgDelete(activeWindow);
  672.                 Adjust_Generic_EditMenu(activeWindow);
  673.                 break;
  674.             case iSelectAll:
  675.                 SelIText(activeWindow, (((DialogPeek)activeWindow)->editField)+1,
  676.                     0, kMaxTextPosition);
  677.                 Adjust_Generic_EditMenu(activeWindow);
  678.                 break;
  679.         }
  680.     }
  681.  
  682.  
  683. /********************* buttonProc **************************/
  684.  
  685. pascal void        buttonProc( DialogPtr theDialog, short theItem)
  686. {
  687.     short    type;
  688.     Rect    box;
  689.     Handle    itemHdl;
  690.     long    response, theColor;
  691.             
  692.         // Outline dialog default Button
  693.     GetDItem(theDialog, ok, &type, &itemHdl, &box);
  694.     
  695.     PenSize(3,3);
  696.     InsetRect( &box, -4, -4);
  697.     FrameRoundRect( &box, 16, 16);
  698.     PenNormal();
  699. }
  700.  
  701.  
  702. /************************ Init_GenericDlg1 ****************************/ 
  703.  
  704. void            Init_GenericDlg1( void )
  705. {
  706.     short        iType;
  707.     Handle        iHandle;
  708.     Rect        iRect;
  709.     DialogPtr    dialog;
  710.     DialogPeek    dlgPeek;
  711.     Ptr            dStorage;
  712.     
  713.     /*    #define     rGenericDlg1            129
  714.         #define         iDefaultOutline        2
  715.         #define         iEditText            5
  716.         #define         iRadioYes            6
  717.         #define         iRadioNo            7
  718.         #define         iCheckBox            9    */
  719.  
  720.     
  721.     dStorage = NewPtrClear(kGenericDlgStorage);
  722.     
  723.     if (! dStorage)
  724.         DoError(eNotEnoughMem, false);
  725.     else
  726.     {
  727.         if (! gWindowsOpen)
  728.             AdjustMenu(mFile, iClose, true);        
  729.         gWindowsOpen++;
  730.  
  731.         dialog = GetNewDialog(rGenericDlg1, dStorage, kMoveToFront);
  732.         if (dialog)
  733.         {
  734.             SetPort(dialog);
  735.             
  736.                 // Default Button Outline
  737.             GetDItem(dialog, iDefaultOutline, &iType, &iHandle, &iRect);
  738.             SetDItem(dialog, iDefaultOutline, iType, buttonProc, &iRect);
  739.             
  740.                 // Set Insertion Caret
  741.             SelIText(dialog, iEditText, 0,0);
  742.             dlgPeek = (DialogPeek)dialog;
  743.             gCur_DlgText = (dlgPeek->textH);
  744.             
  745.                 // Default Radio setting
  746.             GetDItem(dialog, iRadioYes, &iType, &iHandle, &iRect);
  747.             SetCtlValue(iHandle, true);
  748.             
  749.                 // Default Check box setting
  750.             GetDItem(dialog, iCheckBox, &iType, &iHandle, &iRect);
  751.             SetCtlValue(iHandle, true);
  752.             
  753.                 // Identify the window type
  754.             SetWRefCon(dialog, (long)rGenericDlg1);
  755.             
  756.                 // Maintain Undo
  757.             gCanUndo = false;
  758.             
  759.                 // Set up the Edit menu
  760.             Adjust_Generic_EditMenu( dialog );
  761.         }
  762.         else
  763.             DoError(eDialogNotFound, true);
  764.     }
  765. }
  766.  
  767.  
  768. /************************ Init_GenericDlg2 ****************************/ 
  769.  
  770. void            Init_GenericDlg2( void )
  771. {
  772.     short        iType;
  773.     Handle        iHandle;
  774.     Rect        iRect;
  775.     DialogPtr    dialog;
  776.     DialogPeek    dlgPeek;
  777.     Ptr            dStorage;
  778.     
  779.     /*    #define     rGenericDlg2            130
  780.         #define         iDefaultOutline        2
  781.         #define         iEditText            5
  782.         #define         iRadioFirstDay        6
  783.         #define         iFirstCheckBox        14    */
  784.  
  785.     
  786.     dStorage = NewPtrClear(kGenericDlgStorage);
  787.     
  788.     if (! dStorage)
  789.         DoError(eNotEnoughMem, false);
  790.     else
  791.     {
  792.         if (! gWindowsOpen)
  793.             AdjustMenu(mFile, iClose, true);        
  794.         gWindowsOpen++;
  795.  
  796.         dialog = GetNewDialog(rGenericDlg2, dStorage, kMoveToFront);
  797.         if (dialog)
  798.         {
  799.             SetPort(dialog);
  800.             
  801.             /* This dialog does not have a default button */
  802.                         
  803.                 // Set Insertion Caret
  804.             SelIText(dialog, iEditText, 0,0);
  805.             dlgPeek = (DialogPeek)dialog;
  806.             gCur_DlgText = (dlgPeek->textH);
  807.             
  808.                 // Default Radio setting
  809.             GetDItem(dialog, iRadioFirstDay, &iType, &iHandle, &iRect);
  810.             SetCtlValue(iHandle, true);
  811.             SetCRefCon((ControlHandle)iHandle, (long)iRadioFirstDay);
  812.                     
  813.                 // Identify the window type
  814.             SetWRefCon(dialog, (long)rGenericDlg2);
  815.             
  816.                 // Maintain Undo
  817.             gCanUndo = false;
  818.             
  819.                 // Set up the Edit menu
  820.             Adjust_Generic_EditMenu( dialog );
  821.         }
  822.         else
  823.             DoError(eDialogNotFound, true);
  824.     }
  825. }
  826.  
  827.  
  828. /********************* Handle_GenericDialog ****************************/ 
  829.  
  830. void    Handle_GenericDialog( EventRecord *event, long whichDlg )
  831. {
  832.     short            iHit = 0;
  833.     DialogPtr        dialog;
  834.     My_UndoRec        preEditState, postEditState;
  835.     
  836.     /*    This routine contains the framework of handling dialog events,
  837.         it farms out the processing as needed to specific handlers
  838.         for the individual dialogs that come through                */
  839.     
  840.     switch (whichDlg)    // Process keyDown event for buttons if needed
  841.     {
  842.         case rGenericDlg1:
  843.             if (Keydown_Button(event, ok, kOnlyButton))
  844.             {
  845.                 Close_GenericDialog(FrontWindow());
  846.                 goto job_finished;
  847.             }
  848.             break;
  849.     }
  850.     
  851.     preEditState = Get_UndoInfo(FrontWindow());
  852.     
  853.     if (DialogSelect(event, &dialog, &iHit))
  854.     {
  855.         switch (whichDlg)
  856.         {
  857.             case rGenericDlg1:
  858.                 ProcessEvt_GenericDlg1( dialog, iHit);
  859.                 break;
  860.             case rGenericDlg2:
  861.                 ProcessEvt_GenericDlg2( dialog, iHit);
  862.                 break;
  863.         }
  864.     }
  865.     
  866.     if (iHit != ok)
  867.     {
  868.         postEditState = Get_UndoInfo(FrontWindow());
  869.         if (postEditState.undoItem != preEditState.undoItem)
  870.         {
  871.             gCanUndo = false;    // User changed active Edit Text item
  872.             Adjust_Generic_EditMenu(FrontWindow());
  873.         }
  874.         else
  875.         {
  876.             if (preEditState.undoString[0] > postEditState.undoString[0]+1)
  877.             {
  878.                 gUndo_Info = preEditState;    // User selected & deleted chars
  879.                 gCanUndo = true;
  880.             }
  881.             Maintain_EditMenu(FrontWindow(), &preEditState);
  882.         }
  883.     }
  884.     
  885. job_finished:
  886.     ;    // Keep the compiler happy
  887. }
  888.  
  889.  
  890. /********************** ProcessEvt_GenericDlg1 *******************************/ 
  891.  
  892. void    ProcessEvt_GenericDlg1( DialogPtr dialog, short iHit )
  893. {
  894.     short            iType;
  895.     Handle            iHandle;
  896.     Rect            iRect;
  897.  
  898.     switch (iHit)
  899.     {
  900.         case iRadioYes:
  901.         case iRadioNo:
  902.             GetDItem(dialog, iRadioYes, &iType, &iHandle, &iRect);
  903.             SetCtlValue(iHandle, (!(GetCtlValue(iHandle))));
  904.             GetDItem(dialog, iRadioNo, &iType, &iHandle, &iRect);
  905.             SetCtlValue(iHandle, (!(GetCtlValue(iHandle))));
  906.             break;
  907.         case iCheckBox:
  908.             GetDItem(dialog, iCheckBox, &iType, &iHandle, &iRect);
  909.             SetCtlValue(iHandle, (!(GetCtlValue(iHandle))));
  910.             break;
  911.         case ok:
  912.             Close_GenericDialog(dialog);
  913.             break;
  914.     }
  915. }
  916.  
  917.  
  918. /********************** ProcessEvt_GenericDlg2 *************************/ 
  919.  
  920. void    ProcessEvt_GenericDlg2( DialogPtr dialog, short iHit )
  921. {
  922.     short            iType;
  923.     Handle            iHandle, firstRadioH;
  924.     Rect            iRect;
  925.     long            lastRadioOn;
  926.  
  927.     switch (iHit)
  928.     {
  929.         case iRadioFirstDay:
  930.         case iRadioFirstDay+1:
  931.         case iRadioFirstDay+2:
  932.         case iRadioFirstDay+3:
  933.         case iRadioFirstDay+4:
  934.         case iRadioFirstDay+5:
  935.         case iRadioFirstDay+6:
  936.             GetDItem(dialog, iRadioFirstDay, &iType, &firstRadioH, &iRect);
  937.             lastRadioOn = GetCRefCon((ControlHandle)firstRadioH);
  938.             GetDItem(dialog, iHit, &iType, &iHandle, &iRect);
  939.             SetCtlValue(iHandle, (!(GetCtlValue(iHandle))));
  940.             GetDItem(dialog, (short)lastRadioOn, &iType, &iHandle, &iRect);
  941.             SetCtlValue(iHandle, (!(GetCtlValue(iHandle))));
  942.             SetCRefCon(firstRadioH, (long)iHit);
  943.             break;
  944.         case iFirstCheckBox:
  945.         case iFirstCheckBox+1:
  946.         case iFirstCheckBox+2:
  947.             GetDItem(dialog, iHit, &iType, &iHandle, &iRect);
  948.             SetCtlValue(iHandle, (!(GetCtlValue(iHandle))));
  949.             break;
  950.         case ok:
  951.             Close_GenericDialog(dialog);
  952.             lastRadioOn = iRadioFirstDay;
  953.             break;
  954.     }
  955. }
  956.  
  957.  
  958. /********************* Close_GenericDialog ******************************/ 
  959.  
  960. void            Close_GenericDialog(DialogPtr dialog)
  961. {
  962.     DialogPeek    myDlgPeek;
  963.     
  964.     gWindowsOpen--;
  965.     if (!gWindowsOpen)
  966.         AdjustMenu(mFile, iClose, false);
  967.  
  968.     myDlgPeek = (DialogPeek)dialog;
  969.     CloseDialog((DialogPtr)dialog);
  970.     DisposePtr(myDlgPeek);
  971.     
  972.     gCanUndo = false;
  973.     AdjustMenu(mEdit, 0, 0);
  974.     DrawMenuBar();
  975. }
  976.  
  977.                 
  978. /*********************** Adjust_Generic_EditMenu ****************************/ 
  979.  
  980. void        Adjust_Generic_EditMenu( DialogPtr dialog )
  981. {
  982.     MenuHandle    menu;
  983.     TEHandle    the_text;
  984.     short        textSize;
  985.     Boolean        menuActive = false;
  986.     long        text_scrap;
  987.     
  988.     menu = GetMHandle(mEdit);
  989.     the_text = ((DialogPeek)dialog)->textH;
  990.     textSize = (**the_text).teLength;
  991.     
  992.         // UNDO ITEM
  993.     if (gCanUndo)
  994.     {
  995.         EnableItem(menu, iUndo);
  996.         menuActive = true;
  997.     }
  998.     else
  999.         DisableItem(menu, iUndo);
  1000.         
  1001.         // COPY, CUT, & CLEAR ITEMS
  1002.     if ((**the_text).selStart != (**the_text).selEnd)
  1003.     {
  1004.         EnableItem(menu, iCut);
  1005.         EnableItem(menu, iCopy);
  1006.         EnableItem(menu, iClear);
  1007.         menuActive = true;
  1008.     }
  1009.     else
  1010.     {
  1011.         DisableItem(menu, iCut);
  1012.         DisableItem(menu, iCopy);
  1013.         DisableItem(menu, iClear);
  1014.     }
  1015.     
  1016.         // PASTE ITEM
  1017.     text_scrap = TEGetScrapLen();
  1018.     if ((! text_scrap) || (text_scrap > (k255Characters - textSize)))
  1019.         DisableItem(menu, iPaste);
  1020.     else
  1021.     {
  1022.         EnableItem(menu, iPaste);
  1023.         menuActive = true;
  1024.     }
  1025.         
  1026.         // SELECT ALL ITEM
  1027.     if (textSize)
  1028.     {
  1029.         menuActive = true;
  1030.         EnableItem(menu, iSelectAll);
  1031.     }
  1032.     else
  1033.         DisableItem(menu, iSelectAll);
  1034.         
  1035.         // If any of the items are active, activate the menu
  1036.     if (menuActive)
  1037.         EnableItem(menu, 0);
  1038.     else
  1039.         DisableItem(menu, 0);
  1040.         
  1041.     DrawMenuBar();    // Enabling/Disabling entire menu requires MenuBar update
  1042. }
  1043.  
  1044.  
  1045. /************************** Do_Undo **********************************/ 
  1046.  
  1047. void        Do_Undo( DialogPtr dialog )
  1048. {
  1049.     short        iType;
  1050.     Handle        iHandle;
  1051.     Rect        iRect;
  1052.     My_UndoRec    swapUndoInfo;
  1053.     
  1054.     swapUndoInfo = Get_UndoInfo((DialogPeek)dialog);
  1055.     
  1056.     GetDItem(dialog, gUndo_Info.undoItem, &iType, &iHandle, &iRect);
  1057.     SetIText(iHandle, gUndo_Info.undoString);
  1058.     SelIText(dialog, gUndo_Info.undoItem, gUndo_Info.undoSelStart,
  1059.                                 gUndo_Info.undoSelEnd);
  1060.     gUndo_Info = swapUndoInfo;
  1061.     Adjust_Generic_EditMenu(dialog);
  1062. }
  1063.  
  1064.  
  1065. /*************************** Get_UndoInfo ******************************/ 
  1066.  
  1067. My_UndoRec    Get_UndoInfo(DialogPeek dialog)
  1068. {
  1069.     My_UndoRec    undo_record;
  1070.     short        iType;
  1071.     Handle        iHandle;
  1072.     Rect        iRect;
  1073.     
  1074.     /* The great thing about dialogs is they provide the necessary info
  1075.         right in the DialogRecord.  The currectly active TE item and a handle
  1076.         to it.    */
  1077.     
  1078.         // Maintain Undo_Info
  1079.     undo_record.undoItem = dialog->editField+1;    // true editField# always +1
  1080.     GetDItem(dialog, undo_record.undoItem, &iType, &iHandle, &iRect);
  1081.     GetIText(iHandle, undo_record.undoString);
  1082.     undo_record.undoSelStart = (**gCur_DlgText).selStart;
  1083.     undo_record.undoSelEnd = (**gCur_DlgText).selEnd;
  1084.     
  1085.     return(undo_record);
  1086. }
  1087.  
  1088.  
  1089. /*********************** Maintain_EditMenu ****************************/ 
  1090.  
  1091. void    Maintain_EditMenu( DialogPtr dialog, My_UndoRec *preEditState )
  1092. {
  1093.     Boolean        adjust_menu = false;
  1094.     short        pre_textSize, post_textSize;
  1095.     short        pre_SelectionRange, post_SelectionRange;
  1096.     short        iType;
  1097.     Handle        iHandle;
  1098.     Rect        iRect;
  1099.     My_UndoRec    curUndoState;
  1100.     
  1101.     pre_textSize = (preEditState->undoString[0]);
  1102.     pre_SelectionRange = (preEditState->undoSelEnd) - (preEditState->undoSelStart);
  1103.  
  1104.             // If something happened in the edit text, make an adjustment
  1105.     post_textSize = (**gCur_DlgText).teLength;
  1106.     if ( post_textSize != pre_textSize){
  1107.         if ( ((pre_textSize) && (!post_textSize))
  1108.             || ((!pre_textSize) && (post_textSize)) )
  1109.             adjust_menu = true;
  1110.     }
  1111.     if (!adjust_menu){
  1112.         post_SelectionRange = (**gCur_DlgText).selEnd - (**gCur_DlgText).selStart;
  1113.         if (post_SelectionRange != pre_SelectionRange){
  1114.             if ( ((!post_SelectionRange) && (pre_SelectionRange))
  1115.                 || ((post_SelectionRange) && (!pre_SelectionRange)) )
  1116.                 adjust_menu = true;
  1117.         }
  1118.     }
  1119.     
  1120.     if (adjust_menu)
  1121.         Adjust_Generic_EditMenu(FrontWindow());
  1122. }
  1123.  
  1124.  
  1125. /********************** AdjustMenu ******************************/
  1126.  
  1127. void    AdjustMenu( short menuID, short item, Boolean switchOn )
  1128. {
  1129.     MenuHandle    menu;
  1130.     
  1131.     menu = GetMHandle(menuID);
  1132.     if (menu)
  1133.     {
  1134.         if (switchOn)
  1135.             EnableItem(menu, item);
  1136.         else
  1137.             DisableItem(menu, item);
  1138.     }
  1139. }
  1140.  
  1141.  
  1142. /************************* Keydown_Button *****************************/ 
  1143.  
  1144. Boolean        Keydown_Button( EventRecord *event, short item_number,
  1145.                              short buttonKind)
  1146. {
  1147.     Boolean            buttonSelected = false;
  1148.     char            theChar;
  1149.     DialogPtr        dialog;
  1150.     ControlHandle    item_h;
  1151.     long            time;
  1152.     short            itype;
  1153.     Rect            box;
  1154.     
  1155.     /* This is a handy routine to process simple keyDown events for
  1156.         cancel/default button in dialogs.  I got the idea from James W's
  1157.         Show_Help code. */ 
  1158.     
  1159.     if ((event->what == keyDown) || (event->what == autoKey))
  1160.     {
  1161.         theChar = event->message & charCodeMask;
  1162.         
  1163.         switch( buttonKind )
  1164.         {
  1165.             case kDefaultButton:
  1166.                 if ((theChar == RETURN_CHAR) || (theChar == ENTER_CHAR))
  1167.                     buttonSelected = true;
  1168.                 break;
  1169.             case kCancelButton:
  1170.                 if ((theChar == TILDE_CHAR) || (theChar == ESCAPE_CHAR))
  1171.                     buttonSelected = true;
  1172.                 break;
  1173.             case kOnlyButton:
  1174.                 if ((theChar == RETURN_CHAR) || (theChar == ENTER_CHAR)
  1175.                     || (theChar == TILDE_CHAR) || (theChar == ESCAPE_CHAR))
  1176.                     buttonSelected = true;
  1177.                 break;
  1178.         }
  1179.         if (buttonSelected)
  1180.             FlashButton(item_number);
  1181.     }
  1182.     return (buttonSelected);
  1183. }
  1184.  
  1185.  
  1186. /************************ FlashButton ********************************/ 
  1187.  
  1188. void    FlashButton( short item_number )
  1189. {
  1190.     DialogPtr        dialog;
  1191.     ControlHandle    item_h;
  1192.     long            time;
  1193.     short            itype;
  1194.     Rect            box;
  1195.  
  1196.     // Hilite's a button selected via a keyDown to show visual button selection
  1197.     dialog = FrontWindow();
  1198.     GetDItem( dialog, item_number, &itype, (Handle *)&item_h, &box );
  1199.     HiliteControl( item_h, inButton );
  1200.     Delay( 9L, &time );
  1201.     HiliteControl( item_h, 0 );
  1202. }
  1203.  
  1204.  
  1205. /************************* Close_AllDialogs *********************/ 
  1206.  
  1207. void            Close_AllDialogs( void )
  1208. {
  1209.     short        windowsOpen, loop;
  1210.     DialogPtr    dialog;
  1211.     
  1212.     windowsOpen = gWindowsOpen;
  1213.     for (loop = 1; loop <= windowsOpen; loop++)
  1214.     {
  1215.         dialog = (DialogPtr)(FrontWindow());
  1216.         switch (GetWRefCon(dialog))
  1217.         {
  1218.             case rShowHelpDlg:
  1219.                 Close_ShowHelp(dialog);
  1220.                 break;
  1221.             case rGenericDlg1:
  1222.             case rGenericDlg2:
  1223.                 Close_GenericDialog(dialog);
  1224.                 break;
  1225.         }
  1226.     }
  1227. }
  1228.  
  1229.  
  1230. /************************** isPressed *******************************/ 
  1231.  
  1232. short    isPressed(unsigned short k )
  1233. {
  1234.                                         /* CODE EXAMPLE FROM THINK REFERENCE */    
  1235.     unsigned char km[16];
  1236.     
  1237.         // k =  any keyboard scan code, 0-127
  1238.     GetKeys( (long *) km);
  1239.     return ( ( km[k>>3] >> (k & 7) ) & 1);
  1240. }
  1241.  
  1242.  
  1243. /********************* Can_OpenMoreWindows ******************************/ 
  1244.  
  1245. Boolean        Can_OpenMoreWindows( void )
  1246. {
  1247.     Boolean        canDo = true;    // Assume OK
  1248.     
  1249.     if (gWindowsOpen == kMax_WindowsOpen)
  1250.     {
  1251.         canDo = false;
  1252.         DoError(eCantOpenNewWindow, false);
  1253.     }
  1254.     
  1255.     return(canDo);
  1256. }
  1257.  
  1258.  
  1259. /******************** DoError *******************************/
  1260.  
  1261. void    DoError( short err, Boolean fatal )
  1262. {
  1263.     Str255        errString;
  1264.     
  1265.     GetIndString( errString, rErrStringsID, err );
  1266.     ParamText( errString, sEmptyString, sEmptyString, sEmptyString );
  1267.     
  1268.     if ( fatal )
  1269.     {
  1270.         gDone = true;
  1271.         StopAlert(rErrorAlertID, nil);
  1272.     }
  1273.     else
  1274.         NoteAlert(rErrorAlertID, nil );
  1275. }
  1276.